package hu.bme.mit.androtext.gen.ui.builder;

import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
import hu.bme.mit.androtext.androgen.androGenDsl.TargetApplication;
import hu.bme.mit.androtext.gen.IGeneratorSlots;
import hu.bme.mit.androtext.gen.gen2.AndroTextGeneratorMain;
import hu.bme.mit.androtext.gen.util.AndroidConstants2;
import hu.bme.mit.androtext.gen.util.AndroidProjectUtil;
import hu.bme.mit.androtext.gen.util.GeneratorUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.xtext.builder.BuilderParticipant;
import org.eclipse.xtext.builder.EclipseResourceFileSystemAccess;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.resource.IContainer;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.IResourceDescriptions;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider;
import org.eclipse.xtext.util.IAcceptor;

import com.google.inject.Inject;

public class AndroTextBuilderParticipant extends
		BuilderParticipant {
	
	private Map<URI, Set<String>> sourceTargetMap = newHashMap();
	
	@Inject
	private ResourceDescriptionsProvider resourceDescriptionsProvider;
	
	@Inject
	private IContainer.Manager containerManager;
	
	@Inject AndroTextGeneratorMain generator;
	
	@Inject
	private IResourceServiceProvider resourceServiceProvider;
	
	@Override
	public void build(IBuildContext context, IProgressMonitor monitor)
			throws CoreException {
//		final IProject builtProject = context.getBuiltProject();
//		IJavaProject javaProject = JavaCore.create(builtProject);
//		if (!javaProject.exists()) {
//			return;
//		}
//		for (IResourceDescription.Delta delta : context.getDeltas()) { 
//			final Set<String> oldFiles = newHashSet();
//			if (sourceTargetMap.containsKey(delta.getUri())) {
//				oldFiles.addAll(sourceTargetMap.get(delta.getUri()));
//			}
//			final Set<String> newFiles = newHashSet();
//			
//			// get the main generator model based on the usage of the changed model
//			Resource resource = null;
//			try {
//				resource = context.getResourceSet().getResource(delta.getUri(), true);
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//			if (resource == null) {
//				continue;
//			}
//			System.out.println("Building resuorce : " + resource.getURI());
//			Collection<TargetApplication> targetApplications = GeneratorUtil.findTargetApplications(resource);
//			
//			for (TargetApplication target : targetApplications) {
//				System.out.println("Building application " + target.getApplication().getName() + " from resource " + resource.getURI());
//				IWorkspace ws = ResourcesPlugin.getWorkspace();
//				IProject project = ws.getRoot().getProject(target.getProjectName());
//				
//				if (!project.exists()) {
//					// create the project
//					AndroidProjectUtil.createEclipseProject(monitor, project, getTarget(target), false);
//				} else {
//					// clean src-gen directory
//					String folderToClean = project.getFolder("src-gen").getLocation().toString();
//					File f = new File(folderToClean);
//					if (f.exists() && f.isDirectory()) {
//						try {
//							GeneratorUtil.cleanFolder(f, null, false, false);
//						}
//						catch (FileNotFoundException e) {
//							e.printStackTrace();
//						}
//					}
//				}
//				IFolder srcGenFolder = project.getFolder("src-gen");
//				IFileSystemAccess fileSystemAccess = getConfiguredFileSystemAccess(srcGenFolder, new IAcceptor<String>() {
//					public void accept(String fileName) {
//						oldFiles.remove(fileName);
//						newFiles.add(fileName);
//					}
//				});
//				configureFileSystemAccessForTarget(fileSystemAccess, project, target);
//				
//				if (delta.getNew() == null) {
//					handleDeletion(delta, context, fileSystemAccess);
//				} else {
//					if (!resourceServiceProvider.canHandle(delta.getUri()))
//						return;
//					if (shouldGenerate(resource, context)) {
//						// collect all resource info
//						IResourceDescriptions index = resourceDescriptionsProvider.createResourceDescriptions();
//						IResourceDescription resDesc = index.getResourceDescription(resource.getURI());
//						List<IContainer> visibleContainers = containerManager.getVisibleContainers(resDesc, index);
//						for (IContainer c : visibleContainers) {
//							for (IResourceDescription rd : c
//									.getResourceDescriptions()) {
//								context.getResourceSet().getResource(
//										rd.getURI(), true);
//								System.out.println(rd.getURI() + " added to build context resourceset!");
//							}
//						}
//						generator.doGenerate(context.getResourceSet(), fileSystemAccess, target);
//						context.needRebuild();
//					}
//				}
//				for (String removeFile : oldFiles) {
//					fileSystemAccess.deleteFile(removeFile);
//				}
//				if (!newFiles.isEmpty()) {
//					sourceTargetMap.put(delta.getUri(), newFiles);
//				}
//				project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
//			}
//		}
	}

	/**
	 * Configures a fileSystemAccess for a {@link TargetApplication}.
	 * @param fileSystemAccess
	 * @param target
	 */
	private void configureFileSystemAccessForTarget(
			IFileSystemAccess fileSystemAccess, IProject project, TargetApplication targetApplication) {
		IFolder srcGen = project.getFolder("src-gen");
		IFolder src = project.getFolder("src");
		if (fileSystemAccess instanceof EclipseResourceFileSystemAccess) {
			EclipseResourceFileSystemAccess fsa = (EclipseResourceFileSystemAccess) fileSystemAccess;
			// configure a file system access for the given Android TargetApplication
			String mainPackage;
			if (targetApplication.getPackageName() == null) {
				mainPackage = targetApplication.getProjectName();
			} else {
				mainPackage = targetApplication.getPackageName();
			}
			mainPackage = mainPackage.replaceAll("[//.]", "/");
			fsa.setOutputPath(srcGen.getFolder(new Path(mainPackage)).getFullPath().toString());
			// set the src-gen folder path
			fsa.setOutputPath(IGeneratorSlots.SRCGEN_SLOT, srcGen.getFullPath().toString());
			fsa.setOutputPath(IGeneratorSlots.SRC_SLOT, src.getFullPath().toString());
			// set the main project folder path
			fsa.setOutputPath(IGeneratorSlots.PROJECT_SLOT, project.getFullPath().toString());
			// set resource folders
			fsa.setOutputPath(IGeneratorSlots.DRAWABLE_SLOT, project.getFolder(AndroidConstants2.RES_DIRECTORY + AndroidConstants2.DRAWABLE_DIRECTORY).getFullPath().toString());
			fsa.setOutputPath(IGeneratorSlots.LAYOUT_SLOT, project.getFolder(AndroidConstants2.RES_DIRECTORY + AndroidConstants2.LAYOUT_DIRECTORY).getFullPath().toString());
			fsa.setOutputPath(IGeneratorSlots.VALUES_SLOT, project.getFolder(AndroidConstants2.RES_DIRECTORY + AndroidConstants2.VALUES_DIRECTORY).getFullPath().toString());
			fsa.setOutputPath(IGeneratorSlots.XML_SLOT, project.getFolder(AndroidConstants2.RES_DIRECTORY + AndroidConstants2.XML_DIRECTORY).getFullPath().toString());
			// set the package folder paths
//			for (String packageName : getAllPackageNames(targetApplication)) {
//				// skip the main package, because that folder already set in the beginning of this method
//				if (packageName == null || packageName.equals(targetApplication.getPackageName())) {
//					continue;
//				} else if (packageName.equals(targetApplication.getProjectName())) {
//					continue;
//				}
//				packageName = packageName.replaceAll("[//.]", "/");
//				fsa.setOutputPath(getNameForPackageName(packageName), srcGen.getFolder(new Path(packageName)).getFullPath().toString());
//				fsa.setOutputPath("src_"+getNameForPackageName(packageName), src.getFolder(new Path(packageName)).getFullPath().toString());
//			}
		} else {
			System.out.println("Not an eclipse based file system access given to this method to configure!");
		}
	}
	
}
